home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / pcr / pcr4_4.lha / DIST / threads / ThreadsTime.c < prev    next >
C/C++ Source or Header  |  1991-12-03  |  7KB  |  223 lines

  1. /* begincopyright
  2.   Copyright (c) 1988 Xerox Corporation. All rights reserved.
  3.   Use and copying of this software and preparation of derivative works based
  4.   upon this software are permitted. Any distribution of this software or
  5.   derivative works must comply with all applicable United States export
  6.   control laws. This software is made available AS IS, and Xerox Corporation
  7.   makes no warranty about the software, its performance or its conformity to
  8.   any specification. Any person obtaining a copy of this software is requested
  9.   to send their name and post office or electronic mail address to:
  10.     PCR Coordinator
  11.     Xerox PARC
  12.     3333 Coyote Hill Rd.
  13.     Palo Alto, CA
  14.   endcopyright */
  15. /*
  16.  * ThreadsTime.c
  17.  *
  18.  * Demers, April 6, 1990 2:51:18 pm PDT
  19.  */
  20.  
  21. #include "xr/BasicTypes.h"
  22. #include "xr/Threads.h"
  23. #include "xr/ThreadsBackdoor.h"
  24. #include "xr/ThreadsSignalsPrivate.h"
  25. #include "xr/ThreadsStatsPrivate.h"
  26.  
  27.  
  28.  
  29. /*
  30.  * Time since boot
  31.  */
  32.  
  33. #define XR_TicksFromTimeval(sec,usec) \
  34.     (((sec)*XR_TICKS_PER_SECOND) + ((usec)/XR_USECS_PER_TICK))
  35.  
  36. #define XR_SetTimevalFromTicks(tvp,ticks) (\
  37.     ((tvp)->tv_sec = (ticks)/XR_TICKS_PER_SECOND), \
  38.     ((tvp)->tv_usec = ((ticks)%XR_TICKS_PER_SECOND)*XR_USECS_PER_TICK) \
  39.     )
  40.  
  41. #define XR_TIMESLICE    1        /* ticks per timeslice    */
  42. #define XR_TICKS_BETWEEN_SET_TIME    (1 * XR_TICKS_PER_SECOND)
  43.  
  44.  
  45. XR_Ticks        XR_ticksPerSecond = XR_TICKS_PER_SECOND;
  46. unsigned        XR_msecsPerTick = XR_MSECS_PER_TICK;
  47. unsigned        XR_usecPerTick = XR_USECS_PER_TICK;
  48.  
  49. XR_Ticks        XR_waitForever = XR_WAIT_FOREVER;
  50. XR_Ticks        XR_endOfTime = XR_END_OF_TIME;
  51.  
  52.  
  53. void
  54. XR_SetBootTime ()
  55. /*
  56.     Initialize boot time for later use.
  57.     Called once before alarm int handler is initialized.
  58. */
  59. {
  60.     if( gettimeofday(&(XR_sysArea->sa_bootTime), NIL) != 0 )
  61.         XR_Panic("SetBootTime");
  62.     XR_InitPSL(&(XR_sysArea->sa_ticksSinceBootLock));
  63.     XR_sysArea->sa_bootTime.tv_usec = 0;
  64.     XR_sysArea->sa_ticksSinceBoot = 0;
  65.     XR_sysArea->sa_ticksSinceBootDeficit = 0;
  66. }
  67.  
  68.  
  69. void
  70. XR_SetTime()
  71. {
  72.     struct timeval tv;
  73.     XR_Ticks newTicksSinceBoot;
  74.     int deltaTicks;
  75.  
  76.     if( gettimeofday(&tv, NIL) != 0 ) XR_Panic("SetTime");
  77.     newTicksSinceBoot = XR_TicksFromTimeval(
  78.         tv.tv_sec-XR_sysArea->sa_bootTime.tv_sec,
  79.         tv.tv_usec
  80.     );
  81.     deltaTicks = ((int)(newTicksSinceBoot - XR_sysArea->sa_ticksSinceBoot));
  82.     if (deltaTicks < 0) {
  83.         XR_sysArea->sa_ticksSinceBootDeficit = -XR_sysArea->sa_numVP;
  84.         /* In this case, we interpret it as a count of alarm signals    */
  85.         /* to ignore for updating tick count, not a real deficit.      */
  86.         /* We assume we never get ahead by much, so we will eventually  */
  87.         /* synchronize, in spite of the sloppiness here.        */ 
  88.     } else {
  89.         XR_sysArea->sa_ticksSinceBootDeficit = deltaTicks;
  90.     }
  91. }
  92.  
  93.  
  94. XR_Ticks
  95. XR_TicksSinceBoot()
  96. /*
  97.     Return number of ticks since PCR was started.
  98. */
  99. {
  100.     return( XR_sysArea->sa_ticksSinceBoot );
  101. }
  102.  
  103.  
  104.  
  105. /*
  106.  * Alarm signals
  107.  */
  108.  
  109. void
  110. XR_AlarmSigHandler (sig, code, scp, addr)
  111.     int sig;
  112.     int code;
  113.     struct sigcontext *scp;
  114.     XR_Pointer addr;
  115. {
  116.     static int ticksUntilSetTime = 0;
  117.     XR_Ticks pvtTicksSinceBoot;
  118.     XR_Ticks deficitAdjustment;
  119.  
  120.     if( scp->sc_onstack ) XR_Panic("AlarmSigHandler 0");
  121.  
  122.     if( XR_vpe == NIL ) return;
  123.     if( XR_currThread == NIL ) /* can happen during startup */ return;
  124.  
  125.     XR_LockErrno();
  126.     pvtTicksSinceBoot = XR_vpe->vpe_ticksSinceBoot + XR_TIMESLICE;
  127.     if (XR_sysArea->sa_ticksSinceBootDeficit > 0) {
  128.         deficitAdjustment =
  129.             XR_sysArea->sa_ticksSinceBootDeficit/XR_TICKS_BETWEEN_SET_TIME
  130.             + 1;
  131.     } else if (XR_sysArea->sa_ticksSinceBootDeficit < 0) {
  132.         /* We should lose this tick in all vp's. */
  133.         deficitAdjustment = -1;
  134.         XR_sysArea->sa_ticksSinceBootDeficit++;
  135.     } else {
  136.         deficitAdjustment = 0;
  137.         /* We son't try to adjust a fast clock.  That shouldn't happen     */
  138.         /* anyway.  If it does, we'll eventually lose enough ticks to    */
  139.         /* make up for it.                        */
  140.     }
  141.     pvtTicksSinceBoot += deficitAdjustment;
  142.     XR_vpe->vpe_ticksSinceBoot = pvtTicksSinceBoot;
  143.     if( !XR_TestAndSet(&(XR_sysArea->sa_ticksSinceBootLock)) ) {
  144.         /*
  145.          * Got the lock, update the clock and release the lock ...
  146.          */
  147. #       if XR_STATS
  148.             XR_sysArea->sa_stats[XR_STATS_HndAlarm] += 1;
  149.             XR_sysArea->sa_stats[XR_STATS_WhenHndAlarm] =
  150.                 XR_sysArea->sa_stats[XR_STATS_Switch];
  151. #       endif /* XR_STATS */
  152.         if( pvtTicksSinceBoot <= XR_sysArea->sa_ticksSinceBoot ) {
  153.             XR_vpe->vpe_ticksSinceBoot = XR_sysArea->sa_ticksSinceBoot;
  154.         } else {
  155.             /* update XR_sysArea->sa_ticksSinceBoot using deficit */
  156.             if( (ticksUntilSetTime -= XR_TIMESLICE) < 0 ) {
  157.                 XR_SetTime();
  158.                 ticksUntilSetTime = XR_TICKS_BETWEEN_SET_TIME;
  159.             } else {
  160.                 XR_sysArea->sa_ticksSinceBoot = pvtTicksSinceBoot;
  161.                 XR_sysArea->sa_ticksSinceBootDeficit -= deficitAdjustment;
  162.             }
  163.             if( XR_TryMeta( /*whence = */ "AlarmSigHandler" ) ) {
  164.                 /*
  165.                  * We now hold the metalock.
  166.                  */
  167.                 XR_sysArea->sa_doTimeouts = XR_DoTimeouts();
  168.                 XR_UnlockMeta();
  169.             } else {
  170.                 /*
  171.                  * Somebody holds the metalock.  It might be this
  172.                  *   processor, so we can't spin waiting for it
  173.                  *   to be released.
  174.                  * Just set XR_sysArea->sa_doTimeouts and let the
  175.                  *   next call to Switch do the work.
  176.                  */
  177.                 XR_sysArea->sa_doTimeouts = TRUE;
  178.             }
  179.         }
  180.         XR_Unset(&(XR_sysArea->sa_ticksSinceBootLock));
  181.     } else {
  182.         /*
  183.          * Another VP holds the lock, defer to it ...
  184.          */
  185.         XR_vpe->vpe_ticksSinceBoot = (
  186.             (pvtTicksSinceBoot < XR_sysArea->sa_ticksSinceBoot)
  187.                 ? XR_sysArea->sa_ticksSinceBoot
  188.                 : pvtTicksSinceBoot
  189.         );
  190.     }
  191.     {
  192.         extern XR_VPE XR_SlowVP();
  193.         register XR_VPE vp = XR_SlowVP();
  194.         
  195.         if (vp != NIL && vp != XR_vpe) {
  196.             XR_RequestResched(vp);
  197.         }
  198.     }
  199.     XR_RequestResched( XR_vpe );
  200.     XR_UnlockErrno();
  201. }
  202.  
  203.  
  204. void
  205. XR_AlarmSigHandlerInit (installed)
  206.     bool installed;
  207. /*
  208.     Arrange for periodic SIGALRM interrupts on VPs but not IOPs.
  209.     KLUDGE: the first interrupt doesn't occur for a while,
  210.       to give thread initialization time to complete. 
  211.     Called independently on each processor (not just VPs).
  212. */
  213. {
  214.     if( (XR_vpe != NIL) && installed ) {
  215.     struct itimerval itv;
  216.     XR_SetTimevalFromTicks(&(itv.it_interval), XR_TIMESLICE);
  217.     XR_SetTimevalFromTicks(&(itv.it_value), 2*XR_TICKS_PER_SECOND);
  218.     if( setitimer(ITIMER_REAL, &itv, NIL) != 0 )
  219.         XR_Panic("AlarmSigHandlerInit 0");
  220.     }
  221. }
  222.  
  223.